<?php

/**
 * @author: b3h4 (baloghbh@gmail.com)
 */
abstract class cStruct
{
    /**
     * @param mixed $values
     */
    public function __construct($values)
    {
        if (is_array($values))
        {
            $this->initByArray($values);
        }
        else if (is_object($values))
        {
            $this->initByObject($values);
        }
    }

    /**
     * Set the Struct's properties (except objects) from an array.
     *
     * @param array $values
     */
    public function initByArray(array $values)
    {
        $struct_props = array($this);
        foreach ($values as $property => $value)
        {
            if ( ! is_object($value))
            {
                $this->$property = $value;
            }
        }
        unset($struct_props);
    }

    /**
     * Set the Struct's properties (except objects) from an (same struct class) object.
     *
     * @param object $values
     */
    public function initByObject($values)
    {
        if ($values instanceof $this)
        {
            $struct_props = (array)$this;

            foreach ($struct_props as $property => $value)
            {
                if ( ! is_object($values->$property))
                {
                    $this->$property = $values->$property;
                }
            }
        }
        else
        {
            throw new RuntimeException( "Cannot init < ".get_class($this).
                                        " > by < ".get_class($values)." >!");
        }
    }

    /**
     * Clone object
     */
    public function __clone()
    {
        $struct_props = array($this);
        foreach ($struct_props as $property => $value)
        {
            if (is_object($value))
            {
                $that->$property = clone $value;
            }
            else
            {
                $that->$property = $value;
            }
        }
        unset($struct_props);
    }

    /**
     * @param string $name
     */
    public function __get($name)
    {
        throw new RuntimeException("Theres no < {$name} > property to get!");
    }

    /**
     * @param string $name
     * @param mixed $value
     */
    public function __set($name, $value)
    {
        throw new RuntimeException("Theres no < {$name} > property to set < {$value} >!");
    }
}

# EOF